package com.ball.snake;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.os.Build;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

/**
 * Created by Administrator on 2018/9/14 0014.
 */

class MyView extends SurfaceView implements SurfaceHolder.Callback,Runnable {
    private final SurfaceHolder holder;
    private final float scaleX;
    private final float scaleY;
    private boolean isRun;
    private final GestureDetector gestureDetector;
    private Paint paint;
    private boolean gameOver;
    private ArrayList<Block> blocks;
    private Block head;
    private Food food;
    //2
    private GameState gameState;
    private int step;
    //3
    private RectF rectF;
    private int count;
    private int score;
    //6
    private MyMusic myMusic;
    private Food tasteFood;
    private int color[]={Color.BLACK,Color.WHITE,Color.RED};
    private Random random;
    private int r;

    public MyView(Context context) {
        super(context);
        holder=getHolder();
        holder.addCallback(this);
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);
        blocks=new ArrayList<>();
        Point screenSize=new Point();
        random=new Random();
        WindowManager windowManager=(WindowManager)context.getSystemService(
                Context.WINDOW_SERVICE
        ) ;
        if(windowManager!=null){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                windowManager.getDefaultDisplay().getRealSize(screenSize);
            }else{
                windowManager.getDefaultDisplay().getSize(screenSize);
            }
        }
        scaleX=(float)screenSize.x/768;
        scaleY=(float)screenSize.y/1280;
        food=new Food();
        init();
        gestureDetector=new GestureDetector(context, new GestureDetector.SimpleOnGestureListener(){
                    @Override
                    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                        Log.i("onFling","手指快速移动并抬起的瞬间触发");
                        float x=e1.getX()-e2.getX();
                        float y=e1.getY()-e2.getY();
                        if(Math.abs(x)>Math.abs(y)){
                            if(x>0){
                                Log.i("onFling","手势向左");

                                if (gameState==GameState.REVERSE){
                                    if(head.getDir()!=Block.LEFT) {
                                        head.setDir(Block.RIGHT);
                                    }
                                }else{
                                    if (gameState==GameState.FAST){
                                        Block.speed=10;
                                    }
                                    if(head.getDir()!=Block.RIGHT){
                                        head.setDir(Block.LEFT);
                                    }

                                }
                            }else{
                                Log.i("onFling","手势向右");
                                if (gameState==GameState.REVERSE){
                                    if (head.getDir()!=Block.RIGHT){
                                        head.setDir(Block.LEFT);
                                    }
                                }else{
                                    if (gameState==GameState.FAST){
                                        Block.speed=10;
                                    }
                                    if(head.getDir()!=Block.LEFT){
                                        head.setDir(Block.RIGHT);
                                    }
                                }
                            }
                        }else{
                            if(y>0){
                                Log.i("onFling","手势向上");
                                if (gameState==GameState.REVERSE){
                                    if (head.getDir()!=Block.UP){
                                        head.setDir(Block.DOWN);
                                    }
                                }else {
                                    if (gameState==GameState.FAST){
                                        Block.speed=10;
                                    }
                                    if(head.getDir()!=Block.DOWN){
                                        head.setDir(Block.UP);
                                    }
                                }
                            }else{
                                Log.i("onFling","手势向下");
                                if (gameState==GameState.REVERSE){
                                    if (head.getDir()!=Block.DOWN){
                                        head.setDir(Block.UP);
                                    }
                                }else{
                                    if (gameState==GameState.FAST){
                                        Block.speed=10;
                                    }
                                    if(head.getDir()!=Block.UP){
                                        head.setDir(Block.DOWN);
                                    }
                                }
                            }
                        }
                        return super.onFling(e1, e2, velocityX, velocityY);
                    }


                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        if(gameOver){
                            init();
                        }
                        return super.onDoubleTap(e);
                    }

                    @Override
                    public boolean onSingleTapConfirmed(MotionEvent e) {
                        singleTap(e);
                        return super.onSingleTapConfirmed(e);
                    }

                    @Override
                    public void onLongPress(MotionEvent e) {
                        super.onLongPress(e);
                        if (gameState==GameState.FAST){
                            Block.speed=20;
                        }else if (gameState==GameState.ENDLESS||gameState==GameState.REVERSE||gameState==GameState.TASTE){
                            init();
                        }else if (gameState==GameState.DESCRIPTION_REVERSE||gameState==GameState.DESCRIPTION_ENDLESS||gameState==GameState.DESCRIPTION_FAST){
                            gameState=GameState.MENU;
                        }
                    }
                });
    }



    private void singleTap(MotionEvent e){
        switch (gameState){
            case LOGO:
                gameState=GameState.MENU;
                step=1000;
                break;
            case MENU:
                myMusic.stop();
                rectF.set(410*scaleX,270*scaleY,720*scaleX,350*scaleY);
                if (rectF.contains(e.getX(),e.getY())){
                    gameState=GameState.DESCRIPTION_ENDLESS;
                }
                rectF.set(410*scaleX,380*scaleY,720*scaleX,470*scaleY);
                if (rectF.contains(e.getX(),e.getY())){
                    gameState=GameState.DESCRIPTION_REVERSE;
                }
                rectF.set(410*scaleX,490*scaleY,720*scaleX,590*scaleY);
                if(rectF.contains(e.getX(),e.getY())){
                    gameState=GameState.DESCRIPTION_FAST;
                }
                rectF.set(410*scaleX,600*scaleY,720*scaleX,710*scaleY);
                if (rectF.contains(e.getX(),e.getY())){
                    gameState=GameState.DESCRIPTION_TASTE;
//                    Toast.makeText(this.getContext(),"更多精彩，尽情期待", Toast.LENGTH_SHORT).show();
                }
                break;
            case DESCRIPTION_ENDLESS:
            case DESCRIPTION_REVERSE:
            case DESCRIPTION_FAST:
            case DESCRIPTION_TASTE:
                if (gameState==GameState.DESCRIPTION_ENDLESS){
                    gameState=GameState.ENDLESS;
                }
                if (gameState==GameState.DESCRIPTION_REVERSE){
                    gameState=GameState.REVERSE;
                }
                if (gameState==GameState.DESCRIPTION_FAST){
                    gameState=GameState.FAST;
                }
                if (gameState==GameState.DESCRIPTION_TASTE){
                    gameState=GameState.TASTE;
                }
                myMusic.stop();
                break;


            case ENDLESS:
                if (!gameOver)
                    gameState = GameState.STOP_ENDLESS;
                break;

            case REVERSE:
                if (!gameOver)
                gameState=GameState.STOP_REVERSE;
                break;
            case FAST:
                if (!gameOver)
                    gameState=GameState.STOP_FAST;
                break;
            case TASTE:
                if (!gameOver)
                    gameState=GameState.STOP_TASTE;
                break;
            case STOP_ENDLESS:
                gameState=GameState.ENDLESS;
                break;
            case STOP_REVERSE:
                gameState=GameState.REVERSE;
                break;
            case STOP_FAST:
                gameState=GameState.FAST;
                break;
            case STOP_TASTE:
                gameState=GameState.TASTE;
                break;
        }
    }
    private void init(){
        score=0;
        count++;
        Block.speed=10;
        if (count==1){
            gameState=GameState.LOGO;
        }else{
            gameState=GameState.MENU;
        }

        myMusic=new MyMusic(getContext());

        rectF=new RectF();
        gameOver=false;
        blocks.clear();
        for (int i=0;i<10;i++){
            blocks.add(new Block(300+Block.WIDTH*i,100,Block.LEFT));
        }
        head=blocks.get(0);
        head.setColor(Color.CYAN);
        setFood();
    }

    private void setTasteFood(){
         r=random.nextInt(3);
        tasteFood=new Food();
        tasteFood.reset();
        tasteFood.setColor(color[r]);
        for (Block block:blocks){
            if (block.getX()==tasteFood.getX()&&block.getY()==tasteFood.getY()){
                setTasteFood();
                break;
            }
        }
    }
    private void setFood() {
        food.reset();
        for (Block block:blocks){
            if (block.getX()==food.getX()&&block.getY()==food.getY()){
                setFood();
                break;
            }
        }
    }




    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        isRun=true;
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        isRun=false;
    }

    @Override
    public void run() {
        while (isRun){
            long startTime=System.currentTimeMillis();
            logic();
            redraw();
            long endTime=System.currentTimeMillis();
            long diffTime=endTime-startTime;
            if(diffTime<1000/60){
                try {
                    Thread.sleep(1000/60-diffTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void logic(){
        switch (gameState){
            case LOGO:
                step+=5;
                if (step==1000){
                    gameState=GameState.MENU;
                }
                break;
            case MENU:
                myMusic.play("menu.mp3");
                break;
            case DESCRIPTION_FAST:
            case DESCRIPTION_REVERSE:
            case DESCRIPTION_ENDLESS:
            case DESCRIPTION_TASTE:
                myMusic.play("description.mp3");
                break;
            case FALSE:
                myMusic.play("false.mp3");
                break;
            case STOP_REVERSE:
            case STOP_FAST:
            case STOP_ENDLESS:
            case STOP_TASTE:
                myMusic.play("stop.mp3");
                break;
            case ENDLESS:
            case FAST:
            case REVERSE:
            case TASTE:
                myMusic.play("start.mp3");
                for (Block block:blocks){
                    block.logic();
                }
                for (int i=blocks.size()-1;i>0;i--){
                    blocks.get(i).setDir(blocks.get(i-1).getDir());
                }
                outBounds();
                eatFood();
                eatSelf();
                break;

        }
    }

    private void eatFood() {
        if(head.getX()==food.getX()&&head.getY()==food.getY()){
            blocks.get(0).setColor(Color.CYAN);
            Block end=blocks.get(blocks.size()-1);
            switch (end.getDir()){
                case Block.LEFT:
                    blocks.add(new Block(end.getX()+Block.WIDTH,end.getY(),end.getDir()));
                    blocks.add(new Block(end.getX()+Block.WIDTH*2,end.getY(),end.getDir()));
                    break;
                case Block.RIGHT:
                    blocks.add(new Block(end.getX()-Block.WIDTH,end.getY(),end.getDir()));
                    blocks.add(new Block(end.getX()-Block.WIDTH*2,end.getY(),end.getDir()));
                    break;
                case Block.UP:
                    blocks.add(new Block(end.getX(),end.getY()+Block.WIDTH,end.getDir()));
                    blocks.add(new Block(end.getX(),end.getY()+Block.WIDTH*2,end.getDir()));
                    break;
                case Block.DOWN:
                    blocks.add(new Block(end.getX(),end.getY()-Block.WIDTH,end.getDir()));
                    blocks.add(new Block(end.getX(),end.getY()-Block.WIDTH*2,end.getDir()));
                    break;
            }
            setFood();
            if (gameState==GameState.TASTE){
                setTasteFood();
            }
            score+=10;
        }
      if (gameState==GameState.TASTE){
          if (tasteFood!=null){
              if(head.getX()==tasteFood.getX()&&head.getY()==tasteFood.getY()){
                  if (r==0){
                      blocks.get(0).setColor(Color.BLACK);
                      gameOver=true;
                      gameState=GameState.FALSE;
                  }
                  if (r==1){
                      blocks.get(0).setColor(Color.WHITE);
                      Block end=blocks.get(blocks.size()-1);
                      switch (end.getDir()){
                          case Block.LEFT:
                              blocks.add(new Block(end.getX()+Block.WIDTH,end.getY(),end.getDir()));
                              break;
                          case Block.RIGHT:
                              blocks.add(new Block(end.getX()-Block.WIDTH,end.getY(),end.getDir()));
                              break;
                          case Block.UP:
                              blocks.add(new Block(end.getX(),end.getY()+Block.WIDTH,end.getDir()));
                              break;
                          case Block.DOWN:
                              blocks.add(new Block(end.getX(),end.getY()-Block.WIDTH,end.getDir()));
                              break;
                      }
                      setTasteFood();
                      score+=30;
                  }
                  if (r==2){
                      blocks.get(0).setColor(Color.RED);
                      if (blocks.size()>=3){
                          for (int i=0;i<3;i++){
                              blocks.remove(blocks.size()-1);
                          }
                          score+=30;
                      }else{
                          gameOver=true;
                          gameState=GameState.FALSE;
                      }

                  }
                  tasteFood=null;
              }
          }
      }
    }
    private void eatSelf() {
        for (int i =4;i<blocks.size();i++){
            if(blocks.get(i).getX()==head.getX()&&blocks.get(i).getY()==head.getY()){
                gameOver=true;
                gameState=GameState.FALSE;
                break;
            }
        }
    }
    private void outBounds(){
      if(head.getX()<0||head.getX()+Block.WIDTH>768
              ||head.getY()<0||head.getY()+Block.WIDTH>1280){
          gameOver=true;
          gameState=GameState.FALSE;
      }
    }


    private void redraw() {
        Canvas lockCanvas=holder.lockCanvas();
        synchronized (holder){
            try {
                myDraw(lockCanvas);
            }catch (Exception e){
             e.printStackTrace();
            }finally {
                if(lockCanvas!=null){
                    holder.unlockCanvasAndPost(lockCanvas);
                }
            }
        }
    }

    private void myDraw(Canvas canvas) {
        canvas.save();
        canvas.scale(scaleX,scaleY);
        paint.reset();
        switch (gameState){
            case LOGO:
                canvas.drawBitmap(getBitmap("logo.png"),0,0,paint);
                break;
            case MENU:
                canvas.drawBitmap(getBitmap("menu.png"),0,0,paint);
                break;
            case DESCRIPTION_ENDLESS:
                canvas.drawBitmap(getBitmap("endless.png"),0,0,paint);
                break;
            case DESCRIPTION_REVERSE:
                canvas.drawBitmap(getBitmap("reverse.png"),0,0,paint);
                break;
            case DESCRIPTION_FAST:
                canvas.drawBitmap(getBitmap("fast.png"),0,0,paint);
                break;
            case DESCRIPTION_TASTE:
                canvas.drawBitmap(getBitmap("taste.png"),0,0,paint);
                break;
            case FALSE:
                try {
                    tasteFood=null;
                    paint.setTextAlign(Paint.Align.LEFT);
                    paint.setTextSize(36);
                    paint.setColor(Color.WHITE);
                    paint.setAlpha(150);
                    canvas.drawText("啊!游戏结束",200,590,paint);
                    canvas.drawText("您的最终得分为:"+score+"!",200,640,paint);
                    canvas.drawText("不服气?双击返回主菜单!",200,690,paint);
                    canvas.drawText("重新再战!",200,740,paint);
                    Thread.sleep(1100);
                    myMusic.stop();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;
            case ENDLESS:
            case REVERSE:
            case FAST:
            case TASTE:
                if (gameState==GameState.ENDLESS){
                    canvas.drawBitmap(getBitmap("bg_endless.png"),0,0,paint);
                }
                if (gameState==GameState.REVERSE){
                    canvas.drawBitmap(getBitmap("bg_reverse.png"),0,0,paint);
                    paint.setTextAlign(Paint.Align.LEFT);
                    paint.setTextSize(36);
                    paint.setColor(Color.WHITE);
                    paint.setAlpha(150);
                    canvas.drawText("蛇的移动方向和滑动的方向相反",50,1180,paint);

                }
                if (gameState==GameState.TASTE){
                    canvas.drawBitmap(getBitmap("bg_taste.png"),0,0,paint);
                }
                if(gameState==GameState.FAST){
                    canvas.drawBitmap(getBitmap("bg_fast.png"),0,0,paint);
                    paint.setTextAlign(Paint.Align.CENTER);
                    paint.setTextSize(36);
                    paint.setColor(Color.WHITE);
                    paint.setAlpha(150);
                    canvas.drawText("长按屏幕可以加快蛇的速度",530,100,paint);
                }else{
                    paint.setTextAlign(Paint.Align.CENTER);
                    paint.setTextSize(36);
                    paint.setColor(Color.WHITE);
                    paint.setAlpha(150);
                    canvas.drawText("长按屏幕可返回主菜单",550,100,paint);
                }
                paint.setTextAlign(Paint.Align.CENTER);
                paint.setTextSize(36);
                paint.setColor(Color.WHITE);
                paint.setAlpha(150);
                canvas.drawText("得分:"+score,100,100,paint);

                paint.setTextAlign(Paint.Align.LEFT);
                paint.setTextSize(36);
                paint.setColor(Color.WHITE);
                paint.setAlpha(150);
                canvas.drawText("点击屏幕任意位置       暂停游戏",50,1230,paint);

                for (Block block:blocks){
                    block.draw(canvas,paint);
                }
                food.draw(canvas,paint);
                if (tasteFood!=null){
                    tasteFood.draw(canvas,paint);
                }
                break;
            case STOP_ENDLESS:
            case STOP_FAST:
            case STOP_REVERSE:
            case STOP_TASTE:
                if (gameState==GameState.STOP_ENDLESS){
                    canvas.drawBitmap(getBitmap("bg_endless.png"),0,0,paint);
                }
                if(gameState==GameState.STOP_REVERSE){
                    canvas.drawBitmap(getBitmap("bg_reverse.png"),0,0,paint);
                }
                if (gameState==GameState.STOP_FAST){
                    canvas.drawBitmap(getBitmap("bg_fast.png"),0,0,paint);
                }
                if (gameState==GameState.STOP_TASTE){
                    canvas.drawBitmap(getBitmap("bg_taste.png"),0,0,paint);
                    paint.setTextAlign(Paint.Align.CENTER);
                    paint.setTextSize(36);
                    paint.setColor(Color.WHITE);
                    paint.setAlpha(150);
                    canvas.drawText("游戏暂停!",384,490,paint);
                    canvas.drawText("黑色:毒药食物,吃了结束游戏",384,590,paint);
                    canvas.drawText("白色:加长食物,吃了变长两节",384,640,paint);
                    canvas.drawText("红色:缩短食物,吃了缩短两节",384,690,paint);
                    canvas.drawText("点击屏幕任意位置开始游戏!",384,790,paint);
                    try {
                        Thread.sleep(900);
                        myMusic.stop();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }else{
                    paint.setTextAlign(Paint.Align.CENTER);
                    paint.setTextSize(36);
                    paint.setColor(Color.WHITE);
                    paint.setAlpha(150);
                    canvas.drawText("游戏暂停!",384,640,paint);
                    canvas.drawText("点击屏幕任意位置开始游戏!",384,690,paint);
                    try {
                        Thread.sleep(900);
                        myMusic.stop();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }

        }
    }

    private Bitmap getBitmap(String path){
        Bitmap bitmap=null;
        try{
           bitmap= BitmapFactory.decodeStream(getContext().getAssets().open(path));
        }catch (IOException e){
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        performClick();
        return true;
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }
}
